/**
 * 安装模块
 * 负责WGT包的安装、解压、文件操作、清理
 */

import versionManager from './version.js'

class InstallManager {
  /**
   * 应用WGT更新（主入口）
   */
  async applyUpdate(wgtPath, onProgress) {
    try {
      console.log('===== 开始应用更新 =====')
      console.log('WGT文件路径:', wgtPath)
      
      if (!wgtPath) {
        throw new Error('WGT文件路径为空')
      }
      
      // 备份当前版本
      if (onProgress) {
        onProgress({
          stage: 'backup',
          progress: 5,
          message: '备份当前版本...'
        })
      }
      await versionManager.backupVersion()
      
      // 应用更新
      if (onProgress) {
        onProgress({
          stage: 'install',
          progress: 10,
          message: '准备安装更新...'
        })
      }
      
      // #ifdef APP-PLUS
      await this.installWgt(wgtPath, onProgress)
      // #endif
      
      // #ifdef H5
      throw new Error('H5平台不支持WGT更新')
      // #endif
      
      console.log('更新应用成功')
    } catch (error) {
      console.error('应用更新失败:', error)
      throw error
    }
  }

  /**
   * 安装WGT包（APP-PLUS专用）
   */
  async installWgt(wgtPath, onProgress) {
    return new Promise((resolve, reject) => {
      // #ifdef APP-PLUS
      console.log('使用plus.runtime.install安装WGT...')
      console.log('WGT路径:', wgtPath)
      
      if (onProgress) {
        onProgress({
          stage: 'install',
          progress: 50,
          message: '正在安装更新...'
        })
      }
      
      plus.runtime.install(wgtPath, {
        force: true
      }, () => {
        console.log('WGT安装成功')
        
        if (onProgress) {
          onProgress({
            stage: 'install',
            progress: 100,
            message: '安装完成'
          })
        }
        
        resolve()
      }, (error) => {
        console.error('WGT安装失败:', error)
        reject(new Error('WGT安装失败: ' + (error.message || '未知错误')))
      })
      // #endif
      
      // #ifdef H5
      reject(new Error('H5平台不支持WGT安装'))
      // #endif
    })
  }

  /**
   * 从ZIP包应用更新（备用方案）
   */
  async applyUpdateFromZip(zipPath, onProgress) {
    try {
      console.log('===== 从ZIP应用更新 =====')
      console.log('ZIP文件路径:', zipPath)
      
      // 解压文件
      const extractPath = await this.extractZip(zipPath, onProgress)
      console.log('解压完成，路径:', extractPath)
      
      // 获取更新文件列表
      const updateFiles = await this.getUpdateFiles(extractPath)
      console.log('需要更新的文件:', updateFiles)
      
      // 复制文件
      let successCount = 0
      for (let i = 0; i < updateFiles.length; i++) {
        const file = updateFiles[i]
        if (onProgress) {
          const progress = Math.floor(((i + 1) / updateFiles.length) * 100)
          onProgress({
            stage: 'copy',
            progress: progress,
            message: `正在更新文件... ${i + 1}/${updateFiles.length}`
          })
        }
        
        try {
          await this.copyFile(file, extractPath)
          successCount++
        } catch (error) {
          console.error(`复制文件失败: ${file}`, error)
        }
      }
      
      console.log(`文件复制完成，成功: ${successCount}/${updateFiles.length}`)
      
      // 清理临时文件
      await this.cleanupTempFiles(zipPath, extractPath)
      
    } catch (error) {
      console.error('从ZIP应用更新失败:', error)
      throw error
    }
  }

  /**
   * 解压ZIP文件
   */
  async extractZip(zipPath, onProgress) {
    return new Promise((resolve, reject) => {
      // #ifdef APP-PLUS
      console.log('=== 开始解压文件 ===')
      console.log('压缩包路径:', zipPath)
      
      if (!zipPath) {
        reject(new Error('压缩包路径为空'))
        return
      }
      
      if (onProgress) {
        onProgress({
          stage: 'extract',
          progress: 10,
          message: '准备解压文件...'
        })
      }
      
      // 请求文件系统访问
      plus.io.requestFileSystem(plus.io.PRIVATE_DOC, (fs) => {
        if (onProgress) {
          onProgress({
            stage: 'extract',
            progress: 30,
            message: '创建解压目录...'
          })
        }
        
        fs.root.getDirectory('update', { create: true }, (dirEntry) => {
          console.log('解压目录创建成功:', dirEntry.fullPath)
          
          if (onProgress) {
            onProgress({
              stage: 'extract',
              progress: 50,
              message: '开始解压...'
            })
          }
          
          const extractDst = plus.io.convertLocalFileSystemURL('_doc/update/')
          console.log('解压目标路径:', extractDst)
          
          // 使用plus.zip.decompress
          plus.zip.decompress(zipPath, extractDst, () => {
            console.log('解压成功')
            
            if (onProgress) {
              onProgress({
                stage: 'extract',
                progress: 100,
                message: '解压完成'
              })
            }
            
            resolve(extractDst)
          }, (error) => {
            console.error('解压失败:', error)
            reject(new Error('解压失败: ' + (error.message || '未知错误')))
          })
        }, (error) => {
          console.error('创建目录失败:', error)
          reject(new Error('创建解压目录失败: ' + (error.message || '未知错误')))
        })
      }, (error) => {
        console.error('文件系统访问失败:', error)
        reject(new Error('文件系统访问失败: ' + (error.message || '未知错误')))
      })
      // #endif
      
      // #ifdef H5
      console.log('H5平台暂不支持解压功能')
      reject(new Error('H5平台暂不支持解压功能'))
      // #endif
    })
  }

  /**
   * 获取需要更新的文件列表
   */
  async getUpdateFiles(extractPath) {
    return new Promise((resolve, reject) => {
      // #ifdef APP-PLUS
      plus.io.resolveLocalFileSystemURL(extractPath, (entry) => {
        const reader = entry.createReader()
        reader.readEntries((entries) => {
          const files = entries
            .filter(e => !e.isDirectory)
            .map(e => e.name)
          resolve(files)
        }, (error) => {
          console.error('读取文件列表失败:', error)
          reject(error)
        })
      }, (error) => {
        console.error('文件系统访问失败:', error)
        reject(error)
      })
      // #endif
      
      // #ifdef H5
      resolve([])
      // #endif
    })
  }

  /**
   * 复制文件
   */
  async copyFile(filePath, extractPath) {
    try {
      const sourcePath = `${extractPath}/${filePath}`
      const targetPath = this.getTargetFilePath(filePath)
      
      // 确保目标目录存在
      await this.ensureDirectoryExists(filePath)
      
      // 复制文件
      await uni.copyFile({
        src: sourcePath,
        dest: targetPath
      })
      
      console.log(`文件已更新: ${filePath}`)
    } catch (error) {
      console.error(`复制文件失败: ${filePath}`, error)
      throw error
    }
  }

  /**
   * 确保目录存在
   */
  async ensureDirectoryExists(filePath) {
    try {
      const dirPath = filePath.substring(0, filePath.lastIndexOf('/'))
      if (dirPath) {
        // #ifdef APP-PLUS
        await plus.io.requestFileSystem(plus.io.PRIVATE_DOC, (fs) => {
          fs.root.getDirectory(dirPath, { create: true }, () => {
            console.log(`目录已创建: ${dirPath}`)
          })
        })
        // #endif
      }
    } catch (error) {
      console.warn(`创建目录失败: ${filePath}`, error)
    }
  }

  /**
   * 获取目标文件路径
   */
  getTargetFilePath(filePath) {
    // #ifdef APP-PLUS
    return plus.io.convertLocalFileSystemURL(`_doc/${filePath}`)
    // #endif
    
    // #ifdef H5
    return `/${filePath}`
    // #endif
    
    return filePath
  }

  /**
   * 清理临时文件
   */
  async cleanupTempFiles(zipPath, extractPath) {
    try {
      // 清理下载的压缩包
      if (zipPath) {
        await uni.removeSavedFile({
          filePath: zipPath
        })
      }
      
      // 清理解压目录（可选）
      if (extractPath) {
        console.log('清理临时文件完成')
      }
    } catch (error) {
      console.warn('清理临时文件失败:', error)
    }
  }

  /**
   * 重启应用
   */
  restartApp() {
    // #ifdef APP-PLUS
    console.log('重启应用...')
    plus.runtime.restart()
    // #endif
    
    // #ifdef H5
    console.log('刷新页面...')
    window.location.reload()
    // #endif
  }
}

export default new InstallManager() 